package com.xquant.pricing.pricingConfig.controller;

import com.github.pagehelper.PageInfo;
import com.xquant.common.security.annotation.RequiresPermissions;
import com.xquant.common.security.utils.SecurityUtils;
import com.xquant.pricing.pricingConfig.mapper.OptionContractMapper;
import com.xquant.pricing.pricingConfig.mapper.TargetParamMapper;
import com.xquant.pricing.pricingConfig.service.PricingConfigAuthorServiceWrapper;
import com.xquant.pricing.utils.CommResponse;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.xquant.common.core.utils.PageUtils.startPage;

/**
 * @author Administrator
 * @Auther: newCloud
 * @Date: 01/03/2022 15:22
 * @Description: newCloud Controller  配置管理
 */
@RestController
@RequestMapping("pricingConfigAuthor")
public class PricingConfigAuthorController {
    @Autowired
    private PricingConfigAuthorServiceWrapper pricingConfigAuthorService;
    @Resource
    private OptionContractMapper optionContractMapper;
    @Resource
    private TargetParamMapper targetParamMapper;

    @Autowired
    private RedissonClient redissonClient;
    // 锁的key，可以是任意唯一标识，例如业务方法名或资源名称等。
    private static final String LOCK_KEY = "cfgLock";
    // 锁等待时间，单位毫秒。超过这个时间还未获取到锁，则返回失败。
    private static final long LOCK_WAIT_TIME = 5000;
    // 锁持有时间，单位毫秒。超过这个时间锁将被自动释放。
    private static final long LOCK_LEASE_TIME = 10000;
    // 时间单位。
    private static final TimeUnit timeUnit = TimeUnit.MILLISECONDS;


    /**
     * 查询 定价配置用户列表
     */
    @RequiresPermissions("pricingconfig:configmanage:list")
    @RequestMapping(value = "/queryPricingConfigAuthorByPage.action")
    public PageInfo<Map> queryPricingConfigAuthorByPage(@RequestParam Map<String, Object> param) {
        startPage();
        param.put("userId", SecurityUtils.getUserId());
        if (StringUtils.isBlank(MapUtils.getString(param, "productType"))) {
            return new PageInfo<Map>(ListUtils.EMPTY_LIST);
        }
        PageInfo<Map> pageInfo = pricingConfigAuthorService.queryPricingConfigAuthorByPage(param);
        return pageInfo;
    }

    /**
     * 查询 定价配置用户组列表
     */
    @RequiresPermissions("pricingconfig:configmanage:list")
    @RequestMapping(value = "/queryGroupPricingConfigAuthorByPage.action")
    public PageInfo<Map> queryGroupPricingConfigAuthorByPage(@RequestParam Map<String, Object> param) {
        startPage();
        param.put("userId", SecurityUtils.getUserId());
        if (StringUtils.isBlank(MapUtils.getString(param, "productType"))) {
            return new PageInfo<Map>(ListUtils.EMPTY_LIST);
        }
        PageInfo<Map> pageInfo = pricingConfigAuthorService.queryGroupPricingConfigAuthorByPage(param);
        return pageInfo;
    }

    /**
     * 查询 定价配置用户权限
     */
    @RequestMapping(value = "/queryPricingUserAuthorByPage.action")
    public PageInfo<Map> queryPricingUserAuthorByPage(@RequestParam Map<String, Object> param) {
        startPage();
        param.put("userId", SecurityUtils.getUserId());
        PageInfo<Map> pageInfo = pricingConfigAuthorService.queryPricingUserAuthorByPage(param);
        return pageInfo;
    }

    /**
     * 定价配置 同步
     */
    @RequestMapping(value = "/executePricingConfigSyncAuthor.action")
    public Object executePricingConfigSyncAuthor(@RequestParam Map<String, Object> param) {
        pricingConfigAuthorService.executePricingConfigSyncAuthor(param);
        return CommResponse.success("同步成功");
    }

    /**
     * 定价配置 新增
     */
    @RequiresPermissions("pricingconfig:configmanage:add")
    @RequestMapping(value = "/savePricingConfig.action")
    @ResponseBody
    public Object savePricingConfig(@RequestParam Map<String, Object> param) {
        Map<String, Object> queryParam = new WeakHashMap<>();
        queryParam.put("productType", param.get("productType"));
        List<Map> list = pricingConfigAuthorService.queryPricingConfigAuthor(param);
        boolean checkName = pricingConfigAuthorService.checkCfgName(param);

        if (list.size() == 0 && checkName) {
            param.put("creater", SecurityUtils.getUserId());
            pricingConfigAuthorService.doSavePricingConfig(param);
            pricingConfigAuthorService.savePricingConfig(param);
        } else if (list.size() != 0) {
            return CommResponse.failure("配置代码已存在，保存失败");
        } else {
            return CommResponse.failure("配置名称已存在，保存失败");
        }

        return CommResponse.success("保存成功");
    }

    /**
     * 查询权限
     *
     * @param param
     * @return
     */
    @RequestMapping(value = "/queryCfgUserAndDeptPerm.action")
    public List queryGroupUserAndDeptPerm(@RequestParam Map<String, Object> param) {
        List list = pricingConfigAuthorService.getGroupUserAndDeptPerm(param);
        return list;
    }

    /**
     * 修改权限
     *
     * @param param
     * @return
     */
    @RequiresPermissions("pricingconfig:configmanage:allocate")
    @RequestMapping(value = "/updateCfgPerm.action")
    public CommResponse updateGroupPerm(@RequestParam Map<String, Object> param) {
        ArrayList<String> userPerms = new ArrayList<>();
        ArrayList<String> deptPerms = new ArrayList<>();

        /** 为读写表赋权*/
        //存放创建人所属部门和上级部门，必须写权限
        ArrayList<String> deptAncestors = new ArrayList<>();
        //存放其他部门
        ArrayList<String> anotherDepts = new ArrayList<>();
        //存放创建人的数组
        ArrayList<String> userSelf = new ArrayList<>();
        //存放其他人的数组
        ArrayList<String> anotherUser = new ArrayList<>();

        Map<String, Object> deptCfgRights = new HashMap<>();
        Map<String, Object> anotherDeptCfgRights = new HashMap<>();
        String allocateDeptAndUsers = param.get("allocateDeptAndUser").toString();
        String userId = String.valueOf(SecurityUtils.getUserId());
        String cfgId = String.valueOf(param.get("cfgId"));
        String cfgRight = String.valueOf(param.get("cfgRight"));
        HashMap map = com.alibaba.fastjson2.JSONObject.parseObject(cfgRight, HashMap.class);
        //创建人所属部门
        String createDeptId = SecurityUtils.getLoginUser().getSysUser().getDeptId().toString();
        deptAncestors.add(createDeptId);
        userSelf.add(userId);

        //将创建人所属部门的上级部门加入deptPerms
    /*    String deptAncestorIds = groupService.getDeptAncestors(createDeptId);
        List<String> deptAncestorIdArrs = Arrays.asList(deptAncestorIds.split(","));
        for (String deptAncestorArr : deptAncestorIdArrs) {
            if ("0".equals(deptAncestorArr) != true) {
                deptPerms.add(deptAncestorArr);
                deptAncestors.add(deptAncestorArr);
            }
        }*/

        for (String allocateDeptAndUser : allocateDeptAndUsers.split(",")) {
            if (allocateDeptAndUser.charAt(0) == 'u') {
                userPerms.add(allocateDeptAndUser.substring(2));
                if (!userId.equals(allocateDeptAndUser.substring(2))) {
                    //不是本人，赋予传过来的权限
                    anotherUser.add(allocateDeptAndUser.substring(2));
                }

            } else if (allocateDeptAndUser.charAt(0) == 'd') {
                deptPerms.add(allocateDeptAndUser.substring(2));
                if (!createDeptId.equals(allocateDeptAndUser.substring(2))) {
                    //不是所属部门，赋予传过来的权限
                    anotherDepts.add(allocateDeptAndUser.substring(2));
                }
            }
        }
        if (userPerms.size() > 0) {
            param.put("userIds", userPerms);
        }
        if (deptPerms.size() > 0) {
            param.put("deptIds", deptPerms);
        }
        List<Map<String, Object>> list = new ArrayList<>();
        Map<String, Object> userCfgRights = new HashMap<>();
        //为创建人单独赋写权限
        userCfgRights.put("userId", userSelf);
        userCfgRights.put("cfgId", cfgId);
        userCfgRights.put("cfgRight", "2");
        list.add(userCfgRights);
        //其他人传过来的权限
        if (anotherUser.size() != 0) {
            for (String authId : anotherUser) {
                Map<String, Object> anotherUserCfgRights = new HashMap<>();
                anotherUserCfgRights.put("userId", authId);
                anotherUserCfgRights.put("cfgId", cfgId);
                anotherUserCfgRights.put("cfgRight", map.get(authId).toString());
                list.add(anotherUserCfgRights);
            }
        }
        pricingConfigAuthorService.insertUserCfgRight(list);
        //为所属部门和上级部门单独赋写权限
        deptCfgRights.put("deptIds", deptAncestors);
        deptCfgRights.put("cfgId", cfgId);
        deptCfgRights.put("cfgRight", "2");
        pricingConfigAuthorService.insertDeptCfgRight(deptCfgRights);
        //为其他部门赋传过来的权限
        anotherDeptCfgRights.put("deptIds", anotherDepts);
        anotherDeptCfgRights.put("cfgId", cfgId);
        anotherDeptCfgRights.put("cfgRight", "2");
        pricingConfigAuthorService.insertDeptCfgRight(anotherDeptCfgRights);


        pricingConfigAuthorService.updateGroupPerm(param);
        return new CommResponse(true, "操作成功");

    }

    /**
     * 定价配置 更新
     */
    @RequiresPermissions("pricingconfig:configmanage:edit")
    @RequestMapping(value = "/updatePricingConfig.action")
    public Object updatePricingConfig(@RequestParam Map<String, Object> param) {
        boolean checkCfgName = pricingConfigAuthorService.checkCfgName(param);
        if (!checkCfgName) {
            return CommResponse.failure("配置名称重复");
        }
        //@view redisson分布式锁
        // 获取锁对象。
        RLock lock = redissonClient.getLock(LOCK_KEY);
        try {
            // 尝试获取锁。参数分别是：等待时间、锁持有时间、时间单位。
            boolean isLocked = lock.tryLock(LOCK_WAIT_TIME, LOCK_LEASE_TIME, timeUnit);
            // 如果获取到锁，则执行业务逻辑。
            if (isLocked) {
                try {
                    pricingConfigAuthorService.updatePricingConfig(param);
                    // 业务处理成功返回true。
                    return CommResponse.success("更新成功");
                } finally {
                    // 释放锁。无论业务逻辑是否成功都需要释放锁。
                    lock.unlock();
                }
            } else { // 如果获取不到锁，则返回false或进行其他处理。例如抛出异常或者稍后重试等。
                // 获取锁失败返回false。根据实际业务需求调整。
                return CommResponse.failure("更新失败，数据正在被更新，请稍后重试");
            }
            // 处理线程中断异常。通常在tryLock方法中抛出。
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt(); // 设置线程中断状态。根据实际业务需求调整。例如可以选择重新尝试获取锁等。
            // 获取锁失败返回false。根据实际业务需求调整。例如可以选择记录日志或者抛出异常等。这里仅为示例，实际应根据业务需求调整。通常在实际项目中会捕获异常并进行相应处理，例如重试或记录日志等操作，而不是简单地返回false或抛出异常。例如：throw new RuntimeException("获取锁失败", e); 或者 return false; 等操作都是可以的，具体取决于你的业务需求和异常处理策略。如果选择重新尝试获取锁，可以使用一个循环或者重试框架来实现这一点，例如使用Spring Retry框架等。这样可以避免在捕获异常后直接返回false或抛出异常，而是给出一个重试的机会直到成功为止。同时，
            return CommResponse.failure("更新失败");
        }
    }

    /**
     * 定价配置 删除
     */
    @RequiresPermissions("pricingconfig:configmanage:remove")
    @RequestMapping(value = "/deletePricingConfig.action")
    public Object deletePricingConfig(@RequestParam Map<String, Object> param) {
        Map<String, Object> queryParams = new WeakHashMap<>();
        queryParams.put("cfgId", param.get("cfgId"));
        queryParams.put("productType", param.get("productType"));

        deletePricingConfigUserAuthor(param);

        return CommResponse.success("删除成功");
    }


    /**
     * 定价配置权限 更新
     */
    @RequiresPermissions("pricingconfig:configmanage:edit")
    @RequestMapping(value = "/updatePricingConfigUserAuthor.action")
    public Object updatePricingConfigUserAuthor(@RequestBody Map<String, Object> params) {

        pricingConfigAuthorService.doUpdatePricingConfigUserAuthor(params);


        return CommResponse.success("更新成功");
    }

    /**
     * 定价配置 删除
     */
    @RequiresPermissions("pricingconfig:configmanage:remove")
    @RequestMapping(value = "/deletePricingConfigUserAuthor.action")
    public Object deletePricingConfigUserAuthor(@RequestParam Map<String, Object> param) {

        pricingConfigAuthorService.deletePricingConfigUserAuthor(param);
        optionContractMapper.deleteContractCfgById(param);
        targetParamMapper.deleteTargetParamCfgById(param);

        return CommResponse.success("保存成功");
    }

    /**
     * 定价配置 更新
     */
    @RequiresPermissions("pricingconfig:configmanage:default")
    @RequestMapping(value = "/updateUserDefaultPricingParam.action")
    @ResponseBody
    public Object updateUserDefaultPricingParam(@RequestParam Map<String, Object> params, HttpServletRequest request) {
//        Long userId = SecurityUtils.getUserId();
//        if (!(userId == 1)) {
//            return CommResponse.failure("修改默认配置，请联系管理员！！！");
//        }
        Map map = new HashMap();
        map.put("cfgId", params.get("cfgId"));
        List<Map<String, Object>> list = optionContractMapper.queryContractCfg(map);
        if (list.size() == 0) {
            return CommResponse.failure("此配置尚没有配置参数，不允许设为默认配置！！！");
        }
        doUpdateUserDefaultPricingParam(params);
        return CommResponse.success("保存成功");
    }

    public void doUpdateUserDefaultPricingParam(Map<String, Object> params) {
        Long userId = SecurityUtils.getUserId();
        params.put("userId", userId);
        pricingConfigAuthorService.updateUserDefaultPricingParam(params);
    }


    public void doSelectOneDefaultPricingParam(String productType, String userId) {
        Map<String, Object> params = new WeakHashMap<>();
        params.put("productType", productType);
        params.put("userId", userId);
        List<Map> deflist = queryPricingConfigUserDefaultAuthor(params, "1");
        if (deflist.size() > 0) {
            return;
        }
        List<Map> list = pricingConfigAuthorService.queryPricingConfigUserAuthor(params).getList();
        if (list.size() == 0) {
            //查询用户创建的cfg
            Map<String, Object> createrParam = new WeakHashMap<>();
            createrParam.put("creater", userId);
            createrParam.put("productType", productType);
            list = pricingConfigAuthorService.queryPricingConfigAuthor(createrParam);
        }
        if (list.size() > 0) {
            params.put("cfgId", list.get(0).get("CFG_ID"));
            pricingConfigAuthorService.updateUserDefaultPricingParam(params);
        }
    }


    public List<Map> queryPricingConfigUserDefaultAuthor(Map<String, Object> params, String isDefault) {
        params.put("isDefault", isDefault);
        return pricingConfigAuthorService.queryPricingConfigUserDefaultAuthor(params);
    }

    @GetMapping("/querySubCfgCountByCfgId.action")
    public int queryContractCfgCountByPPCode(@RequestParam String cfgId) {
        int count1 = optionContractMapper.queryContractCfgCountByCfgId(cfgId);
        int count2 = targetParamMapper.queryUnderlyingCfgCountByCfgId(cfgId);
        return count1 + count2;
    }


}
